package hu.myai.util.web;

import hu.myai.util.Constans;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.net.MalformedURLException;
import java.net.Proxy;
import java.net.SocketAddress;
import java.net.URL;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author bozbalint
 *
 */
public class DownloadURLWithCookies {

    public DownloadURLWithCookies() {
    }

    /**
     * The object used when logging debug,errors,warnings and info.
     * */
    private final Logger log = LoggerFactory.getLogger(this.getClass());

    private static String cookies = "";

    /**
     * Post a string to an URL and get the reply as a string. Returns an empty
     * string if things didn't work out.
     */
    public InputStream getURLGetString(URL url) {

        int counter = 0;
        InputStream rawInStream = null;
        try {

            // URL must use the http protocol!
            HttpURLConnection conn = null;

            do {
                if (conn != null)
                    conn.disconnect();

                if (Constans.proxyHost != null) {

                    SocketAddress proxyAddr = new InetSocketAddress(Constans.proxyHost, Constans.proxyPort);
                    Proxy proxy = new Proxy(Proxy.Type.HTTP, proxyAddr);

                    conn = (HttpURLConnection) url.openConnection(proxy);
                } else {

                    conn = (HttpURLConnection) url.openConnection(Proxy.NO_PROXY);
                }

                conn.setInstanceFollowRedirects(true);
                conn.setRequestMethod("GET");
                conn.setAllowUserInteraction(false); // you may not ask the
                // user
                conn.setRequestProperty("User-Agent",
                        "Mozilla/5.0 (Windows; U; Windows NT 5.1; hu; rv:1.8.1.3) Gecko/20070309 Firefox/2.0.0.3");
                conn.setRequestProperty("Connection", "keep-alive");
                conn.setRequestProperty("Keep-Alive", "300");
                conn.setRequestProperty("Accept", "image/gif");
                conn.setRequestProperty("Accept-Charset", "ISO-8859-1");
                conn.setRequestProperty("Accept-Encoding", "gzip,deflate");
                conn.setRequestProperty("Accept-Language", "en-us;q=0.5,en;q=0.3");

                if (!"".equals(cookies))
                    conn.setRequestProperty("Cookie", cookies);

                if (conn.getResponseCode() >= 300) {
                    log.warn("Warning, Received code (" + conn.getResponseCode() + ") " + conn.getResponseMessage());
                    counter++;
                }

            } while (conn.getResponseCode() >= 303 && counter < 10);

            // get the input stream for reading the reply
            // IMPORTANT! Your body will not get transmitted if you get the
            // InputStream before completely writing out your output first!
            rawInStream = conn.getInputStream();

        } catch (Exception e) {
            log.error("Error - Network may down or not valid URL, " + e.toString());
            throw new RuntimeException("Error - geUrlGetString failed," + e.toString(), e);
        }

        return rawInStream;

    }

    /**
     * Post a string to an URL and get the reply as a string. Returns an empty
     * string if things didn't work out.
     */
    public InputStream getURLPostString(URL url, String body) {

        int counter = 0;
        InputStream rawInStream = null;

        try {
            // URL must use the http protocol!
            HttpURLConnection conn = null;

            do {
                if (conn != null)
                    conn.disconnect();

                if (Constans.proxyHost != null) {

                    SocketAddress proxyAddr = new InetSocketAddress(Constans.proxyHost, Constans.proxyPort);
                    Proxy proxy = new Proxy(Proxy.Type.HTTP, proxyAddr);

                    conn = (HttpURLConnection) url.openConnection(proxy);
                } else {

                    conn = (HttpURLConnection) url.openConnection(Proxy.NO_PROXY);
                }

                conn.setInstanceFollowRedirects(false);
                conn.setRequestMethod("POST");
                conn.setAllowUserInteraction(false); // you may not ask the
                // user
                conn.setDoOutput(true); // we want to send things
                conn.setRequestProperty("User-Agent",
                        "Mozilla/5.0 (Windows; U; Windows NT 5.1; hu; rv:1.8.1.3) Gecko/20070309 Firefox/2.0.0.3");
                conn.setRequestProperty("Connection", "keep-alive");
                conn.setRequestProperty("Keep-Alive", "300");
                conn.setRequestProperty("Accept-Charset", "ISO-8859-2,utf-8;q=0.7,*;q=0.7");
                conn.setRequestProperty("Accept-Encoding", "gzip,deflate");
                conn.setRequestProperty("Accept-Language", "hu-hu,hu;q=0.8,en-us;q=0.5,en;q=0.3");

                // the Content-type should be default, but we set it anyway
                conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
                // the content-length should not be necessary, but we're
                // cautious
                conn.setRequestProperty("Content-Length", Integer.toString(body.length()));

                if (!"".equals(cookies))
                    conn.setRequestProperty("Cookie", cookies);

                // get the output stream to POST our form data
                OutputStream rawOutStream = conn.getOutputStream();
                PrintWriter pw = new PrintWriter(rawOutStream);

                pw.print(body); // here we "send" our body!
                pw.flush();
                pw.close();

                if (conn.getResponseCode() >= 300) {
                    log.warn("Warning, Received code (" + conn.getResponseCode() + ") " + conn.getResponseMessage());
                    counter++;
                }

            } while (conn.getResponseCode() >= 303 && counter < 10);

            cookies = "";
            String headerName = null;
            for (int i = 1; (headerName = conn.getHeaderFieldKey(i)) != null; i++) {
                if (headerName.equals("Set-Cookie")) {
                    String cookie = conn.getHeaderField(i);
                    cookies += cookie.substring(0, cookie.indexOf(';')) + "; ";
                }
            }

            // get the input stream for reading the reply
            // IMPORTANT! Your body will not get transmitted if you get the
            // InputStream before completely writing out your output first!
            rawInStream = conn.getInputStream();

        } catch (Exception e) {
            log.error("Error - exception " + e.toString());
            e.printStackTrace();
        }

        return rawInStream;
    }

    public boolean pushCookies() {
        PrintStream dos;
        try {
            if (cookies != null && !"".equals(cookies)) {
                dos = new PrintStream(new FileOutputStream("session.txt"));
                dos.print(cookies);
                dos.flush();
                dos.close();
            }
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            return false;
        }
        return true;
    }

    public boolean popCookies() {
        LineNumberReader reader;
        try {
            reader = new LineNumberReader(new InputStreamReader(new FileInputStream("session.txt")));

            cookies = reader.readLine();

        } catch (Exception e) {
            log.warn("Warning, No cookie is saved.");
            return false;
        }

        return true;

    }

    public String getCookies() {
        return cookies;
    }

    public void setCookies(String cookies) {
        DownloadURLWithCookies.cookies = cookies;
    }

    public boolean login() {

        String myUrl = new String("https://www.sanford.com.au/sanford/Public/Home/Loggerin.asp?"
                + "username=bozbalint&password=2yftqrdr");

        String urlString = myUrl;
        urlString = urlString.substring(0, urlString.indexOf('?'));

        String bodyString = myUrl;
        bodyString = bodyString.substring(bodyString.indexOf('?') + 1);

        try {
            getURLPostString(new URL(urlString), bodyString);

        } catch (MalformedURLException e) {
            e.printStackTrace();
            return false;
        }

        if ("".equals(cookies) || cookies.indexOf("SessionVarsKey") == -1)
            return false;
        else
            return true;
    }

    public boolean logout() {

        String myUrl = new String("https://www.sanford.com.au/sanford/Public/Home/Loggerout.asp");

        try {
            getURLGetString(new URL(myUrl));

        } catch (MalformedURLException e) {
            e.printStackTrace();
            return false;
        }

        // delete session file
        new File("session.txt").delete();

        return true;
    }

}
